<?php

namespace app\api\service;

use app\common\model\user\UserVisitLog;
use ReflectionClass;
use Exception;
use tmcore\base\BaseService;

/**
 * 用户浏览服务类
 */
class UserVisitService extends BaseService
{

    /**
     * 获取可用参数
     * @param $params
     * @return mixed
     */
    private function getUsableParam($params) {
        // 屏蔽敏感信息
        if (isset($params['password'])) {
            $params['password'] = '******';
        }
        if (isset($params['password_confirm'])) {
            $params['password_confirm'] = '******';
        }
        return  $params;
    }

    /**
     * 获取方法注释
     * @param $request
     * @return mixed|string
     */
    private function getMethodAnnotation($request) {

        try {
            $controller = str_replace('.', '\\', $request->controller());
            $controller = '\\app\\' . app('http')->getName() . '\\controller\\' . $controller;
            $controllerClass = invoke($controller);
            if(!$controllerClass) throw new Exception('找不到控制器');

            $re = new ReflectionClass($controllerClass);
            $doc = $re->getMethod($request->action())->getDocComment();
            if (empty($doc)) {
                throw new Exception('没有给控制器方法添加注释 ' . $doc);
            }
            preg_match('/\s(\w+)/u', $re->getMethod($request->action())->getDocComment(), $values);
            return $values[0];
        } catch (Exception $e) {
            return $e->getMessage();
        }
    }

    /**
     * 获取请求方式
     * @param $request
     * @return string
     */
    private function getRequestType($request) {
        if($request->isGet()) {
            return 'GET';
        } elseif ($request->isPost()) {
            return 'POST';
        } elseif ($request->isDelete()) {
            return 'DELETE';
        } elseif ($request->isPut()) {
            return 'PUT';
        } else {
            return '';
        }
    }

    /**
     * 添加操作记录
     * @param $request
     * @param $userInfo
     * @param $response
     * @param $startTime
     * @param $endTime
     * @return bool
     */
    public function addVisitLog($request, $userInfo, $response, $startTime = 0, $endTime = 0) {
        
        $executeTime = 0; // 执行时间
        if(!$endTime) $endTime = microtime(true);
        if($startTime && $endTime) {
            $executeTime  = number_format(($endTime - $startTime), 4);
        }

        if(is_array($response)) {
            $response_content = json_encode($response, 320);
            $result = $response;
        } else {
            $response_content = $response->getContent();
            $result = json_decode($response_content, true);
        }

        if(UserVisitLog::$error) {
            $status = 0;
        } else {
            if(isset($result['code']) && $result['code'] == 0) {
                $status = 1;
            } else {
                $status = 2;
            }
        }

        $data = [
            'uid' => $userInfo['id'] ?? 0,
            'nickname' => $userInfo['nickname'] ?? '',
            'account' => $userInfo['account'] ?? '',
            'action' => $this->getMethodAnnotation($request),
            'module' => app('http')->getName(),
            'url' => $request->url(),
            'type' => $this->getRequestType($request),
            'ua' => $request->header('User-Agent'),
            'params' => json_encode($this->getUsableParam($request->param()), 320),
            'ip' => $request->ip(),
            'result' => $status>0?$response_content:'',
            'error' => $status == 0?UserVisitLog::$error:'',
            'trace' => $status == 0?UserVisitLog::$trace:'',
            'execute_time' => $executeTime,
            'status' => $status
        ];

        return UserVisitLog::add($data);
    }


}